package main

import (
	"fmt"
	"unsafe"
)

type userinfo struct {
	name string
	age int
	height float32
	eduschool string
	hobby []string
	moreinfo map[string]interface{}
}
type peopleinfo struct {
	name string
	age int
	height float32
	eduschool string
	hobby []string
	moreinfo map[string]interface{}
}

type Integer int  

//后台管理系统中，权限问题，这里涉及了角色，超级管理员，管理员，普通用户
type role struct {
	user userinfo 
	authorization Integer  //1=超级管理员，2=管理员，3=普通用户
}

func main()  {
	//结构体，struct
	//java,php,c++
	//定义自定义类型,两种方式：
	//	1.type
	type integer int
	var intVariables int
	var integerVariables integer
	//intVariables = integerVariables
	fmt.Println(intVariables,integerVariables)
	//如何赋值？类型转换
	intVariables = int(integerVariables)
		//2.struct,组合一定数量的字段完成，值类型
	//type 结构体名 struct {
	//	field1 type1
	//	field2 type2
	//	....
	//}
	//结构体的使用方式1
	var bobo userinfo
	bobo.name = "波哥"
	bobo.age = 18
	bobo.height = 181
	bobo.eduschool = "北京邮电大学"
	bobo.hobby = []string{"coding","运动","旅行"}
	bobo.moreinfo = map[string]interface{}{
		"work":"百度",
		"duty":"产品狗",
	}
	fmt.Printf("name=%s,hobby=%v\n",bobo.name,bobo.hobby)

	//2.:=简短声明来实现一个结构变量
	//	1.声明变量
	//	2.初始化
	//var liuge = userinfo{
	//	name:      "",
	//	age:       0,
	//	height:    0,
	//	eduschool: "",
	//	hobby:     nil,
	//	moreinfo:  nil,
	//}
	huge := userinfo{
		eduschool: "北京电影学院",
		hobby:     []string{"拍电影","唱歌","旅行"},
		moreinfo: map[string]interface{}{
			"role":"演员",
			"earnmoney":300000,
		},
		name:      "胡哥",
		age:       28,
		height:    188,
	}
	fmt.Printf("huge=%v\n",huge)

	//不指定字段名的时候，需要严格的按照定义结构体时候的顺序赋值
	//muge := userinfo{
	//	"慕哥",
	//	"北京大学"
	//}

	xiaoge := userinfo{"小哥",12,120,"小学",[]string{"学习","玩","打游戏"}, map[string]interface{}{"年级":"六年级"}}
	fmt.Printf("xiaoge=%v\n",xiaoge)

	//3.new new(int),new(string),new(T)结构体指针
	//var t *T
	//t = new(T)
	var xiaoming *userinfo
	xiaoming = new(userinfo)
	(*xiaoming).name = "小明"
	(*xiaoming).age = 12
	(*xiaoming).eduschool = "北京小学"
	//xiaoming->(*xiaoming)
	xiaoming.hobby = []string{"学习","玩","打游戏"}
	fmt.Println(xiaoming)

	//4.&地址符，同样是返回的结构体指针
	var xiaohong *userinfo = &userinfo{
		"小红",12,120,"小学",[]string{"学习","玩","打游戏"}, map[string]interface{}{"年级":"五年级"},
	}
	fmt.Println(xiaohong,(*xiaohong))

	//结构体的注意事项：
	//1.结构体是值类型
	user1 := userinfo{
		name:      "user1",
		age:       0,
		height:    0,
		eduschool: "",
		hobby:     nil,
		moreinfo:  nil,
	}
	user2 := user1
	fmt.Printf("user1 = %p,user2 = %p\n",&user1,&user2)
	//2.结构体之间是否可以相互转换？可以转换，前提条件：具有相同的字段（个数，类型，名称)
	user3 := userinfo{
		name:      "user3",
		age:       0,
		height:    0,
		eduschool: "",
		hobby:     nil,
		moreinfo:  nil,
	}

	user4 := peopleinfo{
		name:      "user4",
		age:       0,
		height:    0,
		eduschool: "",
		hobby:     nil,
		moreinfo:  nil,
		//pmoreinfo:nil,
	}

	user3 = userinfo(user4)
	//user3 = user4
	fmt.Println(user3)
	
	//结构体可以做为另一个结构体字段的类型
	superadmin := role{
		user:          userinfo{
			name:      "超级管理员",
			age:       0,
			height:    0,
			eduschool: "",
			hobby:     nil,
			moreinfo:  nil,
		},
		authorization: 1,
	}
	admin := role{
		user:          userinfo{
			name:      "管理员",
			age:       0,
			height:    0,
			eduschool: "",
			hobby:     nil,
			moreinfo:  nil,
		},
		authorization: 2,
	}
	fmt.Println(superadmin,admin)

	//结构体在内存中的布局
	//var xiaohong *userinfo = &userinfo{
	//	"小红",12,120,"小学",[]string{"学习","玩","打游戏"}, map[string]interface{}{"年级":"五年级"},
	//}

	fmt.Printf("name=%p,age=%p,height=%p,eduschool=%p,hobby=%p,moreinfo=%p\n",&xiaohong.name,&xiaohong.age,&xiaohong.height,&xiaohong.eduschool,&xiaohong.hobby,&xiaohong.moreinfo)

	fmt.Printf("name=%d,age=%d,height=%d,eduschool=%d,hobby=%d,moreinfo=%d\n",unsafe.Sizeof(xiaohong.name),unsafe.Sizeof(xiaohong.age),unsafe.Sizeof(xiaohong.height),unsafe.Sizeof(xiaohong.eduschool),unsafe.Sizeof(xiaohong.hobby),unsafe.Sizeof(xiaohong.moreinfo))

	type Hobby struct {
		hobby1 string
		hobby2 string
		hobby3 string
	}
	
	hb := Hobby{
		hobby1: "学习",
		hobby2: "玩",
		hobby3: "打游戏",
	}

	fmt.Printf("hobby1=%p,hobby2=%p,hobby3=%p\n",&hb.hobby1,&hb.hobby2,&hb.hobby3)
}
